/*****************************************************************************/
/*                                                                           */
/*    Domino Operation System System Specific Module                         */
/*                                                                           */
/*    Copyright (C) 2010 Laszlo Arvai                                        */
/*                                                                           */
/*    ------------------------------------------------------------------   */
/*    Network socket API implementation                                      */
/*****************************************************************************/

#ifndef __netSocket_h
#define __netSocket_h
									
#ifndef _WINSOCKAPI_

/*****************************************************************************/
/* Includes                                                                  */
/*****************************************************************************/

#include <netPacketBufferType.h>

///////////////////////////////////////////////////////////////////////////////
// Constants
#define AF_INET         2   // Internet Address Family - UDP, TCP, etc.

#define IP_ADDR_ANY				0   // IP Address for server binding
#define INADDR_ANY				0x00000000 // IP address for server binding.
#define IP_ADDR_BROADCAST 0xffffffff // IP Address for broadcasting

#define MK_IN_ADDR(a,b,c,d) ( (((dosDWord)d) << 24) + (((dosDWord)c) << 16) + (((dosDWord)b) << 8) + a )

#define SOCK_STREAM 100  //Connection based byte streams. Use TCP for the internet address family.
#define SOCK_DGRAM  110  //Connectionless datagram socket. Use UDP for the internet address family.
 
#define IPPROTO_TCP     6   // Indicates TCP for the internet address family.
#define IPPROTO_UDP     17  // Indicates UDP for the internet address family.

#define SOCKET_ERROR            (-1) //Socket error
#define SOCKET_CNXN_IN_PROGRESS (-2) //Socket connection state.
#define SOCKET_DISCONNECTED     (-3) //Socket disconnected

#define INVALID_SOCKET      (0xFE)   // The socket is invalid or could not be opened
#define UNKNOWN_SOCKET      (0xFF)   // The socket is not known

// define maximum number of sockets if needed
#ifndef netMAX_SOCKET
#define netMAX_SOCKET 16
#endif

// big-little endian conversion
#define LITTLE_ENDIAN 
 
#if defined(BIG_ENDIAN) 
 
#define htons(A)	(A) 
#define htonl(A)	(A) 
#define ntohs(A)	(A) 
#define ntohl(A)	(A) 
 
#elif defined(LITTLE_ENDIAN) 
 
#define htons(A)	((((A) & 0xFF00) >> 8) | \
			 (((A) & 0x00FF) << 8)) 
 
#define htonl(A)	((((A) & 0xFF000000) >> 24) | \
			 (((A) & 0x00FF0000) >> 8) | \
			 (((A) & 0x0000FF00) << 8) | \
			 (((A) & 0x000000FF) << 24)) 
 
#define ntohs	htons 
#define ntohl	htohl 
 
#else 
 
#error "User Must define LITTLE_ENDIAN or BIG_ENDIAN!!!" 
 
#endif 
 
///////////////////////////////////////////////////////////////////////////////
// Typedefs
typedef dosByte SOCKET;   //Socket descriptor
typedef dosByte netSOCKET;

// MAC address structure
typedef struct _mac_addr
{
	dosByte v[6];
} MAC_ADDR;

// IP address structure
typedef struct in_addr
{
   union
   {
      union
      {
         struct { dosByte s_b1,s_b2,s_b3,s_b4; } S_un_b;
         struct { dosWord s_w1,s_w2; } S_un_w;
         dosDWord S_addr;
      } S_un;
#define s_addr  S_un.S_addr //can be used for most tcp & ip code
#define s_host  S_un.S_un_b.s_b2 //host on imp
#define s_net   S_un.S_un_b.s_b1 // network
#define s_imp   S_un.S_un_w.s_w2 // imp
#define s_impno S_un.S_un_b.s_b4 // imp number
#define s_lh    S_un.S_un_b.s_b3 // logical host
     dosByte v[4];
     dosWord w[2];
     dosDWord Val;    
  };
} IN_ADDR;

// sockaddr structure
struct sockaddr
{
    unsigned short   sa_family;   //address family
    char    sa_data[14];       //up to 14 bytes of direct address
}; //generic address structure for all address families

// sockaddr_in
struct sockaddr_in
{
    short   sin_family; //Address family; must be AF_INET.
    dosWord sin_port;  //Internet Protocol (IP) port.
    struct  in_addr sin_addr; //IP address in network byte order.
    char    sin_zero[8];  //Padding to make structure the same size as SOCKADDR. 
}; //In the Internet address family

typedef int socklen_t;

typedef struct sockaddr_in SOCKADDR_IN; //In the Internet address family
typedef struct sockaddr SOCKADDR;  // generic address structure for all address families

// Socket state
typedef enum _netSocketState
{
    netSS_CLOSED,   // Socket closed state
    netSS_CREATED, // Socket created state
    netSS_BOUND,   // Socket bound state
//    netSS_LISTEN,  // Socket listen state
//    netSS_IN_PROGRESS, //Socket cnx in progress state
    netSS_READY,  //Socket ready state
//    netSS_ARP_RESOLVE, //Socket ARP resolve state
//    netSS_ARP_VERIFY, //Socket ARP verify state
//    netSS_EST  // Socket established state.
} netSocketState; // Berkeley socket states

// SOCKET sctructure
typedef struct 
{
	dosByte         Type;								//< Socket type
	netSocketState  State;							//< Socket state
	dosWord         LocalPort;					//< Local port
	dosWord         RemotePort;					//< Remote port
	IN_ADDR					RemoteAddress;			//< Remote IP
	netChunkIndex   FirstPendingPacket; //< First received packet waiting for reading
} netSocketInfo;

#define INVALID_TCP_PORT   (0L)  //Invalide TCP port

///////////////////////////////////////////////////////////////////////////////
// Global variables
extern netSocketInfo g_netSockets[];

/*
int listen( SOCKET s, int backlog );
SOCKET accept( SOCKET s, struct sockaddr* addr, int* addrlen );
int connect( SOCKET s, const struct sockaddr* name, int namelen );
int send( SOCKET s, const char* buf, int len, int flags );
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen );
int recv( SOCKET s, char* buf, int len, int flags );
int recvfrom( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen );
int gethostname(char* name, int namelen);
int closesocket( SOCKET s );
*/

#else
/*****************************************************************************/
/* WIN32 drive compatible declarations                                       */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include <krnlTypes.h>

typedef SOCKET netSOCKET;
typedef int socklen_t;

#endif

///////////////////////////////////////////////////////////////////////////////
// Socket functions
void netInitialize(void);
void netCleanUp(void);

dosBool netProcess(void);

netSOCKET netFindSocket( dosByte in_type, dosWord in_local_port );

netSOCKET netSocketOpen( int af, int type, int protocol );
int netBind( netSOCKET s, const struct sockaddr* name, int namelen );
int netConnect( netSOCKET s, const struct sockaddr* name, int namelen );
dosBool netIsConnected( netSOCKET s );
dosBool netIsTXReady(netSOCKET s);

int netRecvfrom( netSOCKET s, char* buf, int len, int flags, struct sockaddr* from, socklen_t* fromlen );
int netReceive( netSOCKET s, char* buf, int len, int flags );
int netSend( netSOCKET s, const char* buf, int len, int flags );
int netSendto( netSOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen );
int netCloseSocket( netSOCKET s );

///////////////////////////////////////////////////////////////////////////////
// BSD socket wrapper macros
#ifndef _netSocket_NO_WRAPPERS
#define socket(a,b,c) netSocketOpen(a,b,c)
#define bind(a,b,c)   netBind(a,b,c)
#define connect(a,b,c)   netConnect(a,b,c)
#define recvfrom(a,b,c,d,e,f)   netRecvfrom(a,b,c,d,e,f)
#define recv(a,b,c,d) netReceive(a,b,c,d)
#define send(a,b,c,d) netSend(a,b,c,d)
#define sendto(a,b,c,d,e,f) netSendto(a,b,c,d,e,f)
#define closesocket(s) netCloseSocket(s)
#endif

#endif